/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.gruposp2p.aularest.model.controller;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import org.gruposp2p.aularest.model.Student;
import java.util.ArrayList;
import java.util.Collection;
import org.gruposp2p.aularest.model.Address;
import org.gruposp2p.aularest.model.Tutor;
import org.gruposp2p.aularest.model.controller.exceptions.NonexistentEntityException;
import org.gruposp2p.aularest.model.controller.exceptions.PreexistingEntityException;

/**
 *
 * @author jj
 */
public class TutorJpaController {

    public TutorJpaController() {
        emf = Persistence.createEntityManagerFactory("AulaRest_PU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Tutor tutor) throws PreexistingEntityException, Exception {
        if (tutor.getStudentCollection() == null) {
            tutor.setStudentCollection(new ArrayList<Student>());
        }
        if (tutor.getAddressCollection() == null) {
            tutor.setAddressCollection(new ArrayList<Address>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Student> attachedStudentCollection = new ArrayList<Student>();
            for (Student studentCollectionStudentToAttach : tutor.getStudentCollection()) {
                studentCollectionStudentToAttach = em.getReference(studentCollectionStudentToAttach.getClass(), studentCollectionStudentToAttach.getId());
                attachedStudentCollection.add(studentCollectionStudentToAttach);
            }
            tutor.setStudentCollection(attachedStudentCollection);
            Collection<Address> attachedAddressCollection = new ArrayList<Address>();
            for (Address addressCollectionAddressToAttach : tutor.getAddressCollection()) {
                addressCollectionAddressToAttach = em.getReference(addressCollectionAddressToAttach.getClass(), addressCollectionAddressToAttach.getId());
                attachedAddressCollection.add(addressCollectionAddressToAttach);
            }
            tutor.setAddressCollection(attachedAddressCollection);
            em.persist(tutor);
            for (Student studentCollectionStudent : tutor.getStudentCollection()) {
                studentCollectionStudent.getTutorCollection().add(tutor);
                studentCollectionStudent = em.merge(studentCollectionStudent);
            }
            for (Address addressCollectionAddress : tutor.getAddressCollection()) {
                Tutor oldTutorIdOfAddressCollectionAddress = addressCollectionAddress.getTutorId();
                addressCollectionAddress.setTutorId(tutor);
                addressCollectionAddress = em.merge(addressCollectionAddress);
                if (oldTutorIdOfAddressCollectionAddress != null) {
                    oldTutorIdOfAddressCollectionAddress.getAddressCollection().remove(addressCollectionAddress);
                    oldTutorIdOfAddressCollectionAddress = em.merge(oldTutorIdOfAddressCollectionAddress);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findTutor(tutor.getId()) != null) {
                throw new PreexistingEntityException("Tutor " + tutor + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Tutor tutor) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tutor persistentTutor = em.find(Tutor.class, tutor.getId());
            Collection<Student> studentCollectionOld = persistentTutor.getStudentCollection();
            Collection<Student> studentCollectionNew = tutor.getStudentCollection();
            Collection<Address> addressCollectionOld = persistentTutor.getAddressCollection();
            Collection<Address> addressCollectionNew = tutor.getAddressCollection();
            Collection<Student> attachedStudentCollectionNew = new ArrayList<Student>();
            for (Student studentCollectionNewStudentToAttach : studentCollectionNew) {
                studentCollectionNewStudentToAttach = em.getReference(studentCollectionNewStudentToAttach.getClass(), studentCollectionNewStudentToAttach.getId());
                attachedStudentCollectionNew.add(studentCollectionNewStudentToAttach);
            }
            studentCollectionNew = attachedStudentCollectionNew;
            tutor.setStudentCollection(studentCollectionNew);
            Collection<Address> attachedAddressCollectionNew = new ArrayList<Address>();
            for (Address addressCollectionNewAddressToAttach : addressCollectionNew) {
                addressCollectionNewAddressToAttach = em.getReference(addressCollectionNewAddressToAttach.getClass(), addressCollectionNewAddressToAttach.getId());
                attachedAddressCollectionNew.add(addressCollectionNewAddressToAttach);
            }
            addressCollectionNew = attachedAddressCollectionNew;
            tutor.setAddressCollection(addressCollectionNew);
            tutor = em.merge(tutor);
            for (Student studentCollectionOldStudent : studentCollectionOld) {
                if (!studentCollectionNew.contains(studentCollectionOldStudent)) {
                    studentCollectionOldStudent.getTutorCollection().remove(tutor);
                    studentCollectionOldStudent = em.merge(studentCollectionOldStudent);
                }
            }
            for (Student studentCollectionNewStudent : studentCollectionNew) {
                if (!studentCollectionOld.contains(studentCollectionNewStudent)) {
                    studentCollectionNewStudent.getTutorCollection().add(tutor);
                    studentCollectionNewStudent = em.merge(studentCollectionNewStudent);
                }
            }
            for (Address addressCollectionOldAddress : addressCollectionOld) {
                if (!addressCollectionNew.contains(addressCollectionOldAddress)) {
                    addressCollectionOldAddress.setTutorId(null);
                    addressCollectionOldAddress = em.merge(addressCollectionOldAddress);
                }
            }
            for (Address addressCollectionNewAddress : addressCollectionNew) {
                if (!addressCollectionOld.contains(addressCollectionNewAddress)) {
                    Tutor oldTutorIdOfAddressCollectionNewAddress = addressCollectionNewAddress.getTutorId();
                    addressCollectionNewAddress.setTutorId(tutor);
                    addressCollectionNewAddress = em.merge(addressCollectionNewAddress);
                    if (oldTutorIdOfAddressCollectionNewAddress != null && !oldTutorIdOfAddressCollectionNewAddress.equals(tutor)) {
                        oldTutorIdOfAddressCollectionNewAddress.getAddressCollection().remove(addressCollectionNewAddress);
                        oldTutorIdOfAddressCollectionNewAddress = em.merge(oldTutorIdOfAddressCollectionNewAddress);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = tutor.getId();
                if (findTutor(id) == null) {
                    throw new NonexistentEntityException("The tutor with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Tutor tutor;
            try {
                tutor = em.getReference(Tutor.class, id);
                tutor.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The tutor with id " + id + " no longer exists.", enfe);
            }
            Collection<Student> studentCollection = tutor.getStudentCollection();
            for (Student studentCollectionStudent : studentCollection) {
                studentCollectionStudent.getTutorCollection().remove(tutor);
                studentCollectionStudent = em.merge(studentCollectionStudent);
            }
            Collection<Address> addressCollection = tutor.getAddressCollection();
            for (Address addressCollectionAddress : addressCollection) {
                addressCollectionAddress.setTutorId(null);
                addressCollectionAddress = em.merge(addressCollectionAddress);
            }
            em.remove(tutor);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Tutor> findTutorEntities() {
        return findTutorEntities(true, -1, -1);
    }

    public List<Tutor> findTutorEntities(int maxResults, int firstResult) {
        return findTutorEntities(false, maxResults, firstResult);
    }

    private List<Tutor> findTutorEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Tutor as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Tutor findTutor(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Tutor.class, id);
        } finally {
            em.close();
        }
    }

    public int getTutorCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Tutor as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
